﻿namespace PasswordStrengthener
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;

    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private string fullHash;

        public MainWindow()
        {
            InitializeComponent();

            foreach (string num in new[] { "1k", "10k", "100k", "1kk", "10kk", "100kk" })
            {
                Button btn = new Button { Content = num };
                btn.Click += (s, e) =>
                {
                    iterationsTextBox.Text = ((Button)s).Content.ToString().Replace("k", "000");
                    iterationsPanel.Visibility = Visibility.Hidden;
                };
                iterationsPanel.Children.Add(btn);
            }
        }

        private void TextBoxPreviewTextInput(object sender, TextCompositionEventArgs e)
        {
            e.Handled = !e.Text.All(ch => char.IsNumber(ch));
        }

        private void IterationsTextBoxTextChanged(object sender, TextChangedEventArgs e)
        {
            if (this.iterationsTextBox.Text.Length > 0)
            {
                this.estimatedTimeLabel.Content = "Estimated time: " +
                    TimeString(Worker.GetTime(long.Parse(this.iterationsTextBox.Text)));
            }
            else
            {
                this.estimatedTimeLabel.Content = string.Empty;
            }
        }

        private static string TimeString(TimeSpan timeSpan)
        {
            if (timeSpan.TotalSeconds < 0.1) return "less than 1/10 of a second";
            if (timeSpan.TotalSeconds < 1) return string.Format("about {0:0.#} seconds", timeSpan.TotalSeconds);
            if (timeSpan.TotalSeconds < 60) return string.Format("about {0:0} seconds", timeSpan.TotalSeconds);
            if (timeSpan.TotalMinutes < 60) return string.Format("about {0:0} minutes", timeSpan.TotalMinutes);
            if (timeSpan.TotalHours < 24) return string.Format("about {0:0} hours", timeSpan.TotalHours);
            if (timeSpan.TotalDays < 365) return string.Format("about {0:0.#} days", timeSpan.TotalDays);
            return string.Format("about {0:0.#} years", timeSpan.TotalDays / 365);
        }

        private void GenerateButtonClick(object sender, RoutedEventArgs e)
        {
            if (this.iterationsTextBox.Text.Length > 0)
            {
                string basePassword = this.basePasswordTextBox.Text;
                long iterations = long.Parse(this.iterationsTextBox.Text);
                new Thread(
                    () =>
                    {
                        fullHash = Worker.Hash(
                            basePassword,
                            iterations,
                            percent => Dispatcher.Invoke(new Action(() => progressBar.Value = percent)));
                        Dispatcher.Invoke(new Action(() => lengthTextBox.Text = "25"));
                        Dispatcher.Invoke(new Action(() => resultTextBox.Text = fullHash.Substring(0, 25)));
                    }).Start();
            }
        }

        private void LengthTextBoxTextChanged(object sender, TextChangedEventArgs e)
        {
            if (lengthTextBox.Text.Length > 0)
            {
                if (int.Parse(lengthTextBox.Text) > fullHash.Length)
                {
                    lengthTextBox.Text = fullHash.Length.ToString();
                }
                resultTextBox.Text = fullHash.Substring(0, int.Parse(lengthTextBox.Text));
            }
        }

        private void IterationsTextBoxGotFocus(object sender, RoutedEventArgs e)
        {
            iterationsPanel.Visibility = Visibility.Visible;
        }

        private void WindowKeyUp(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Escape)
            {
                iterationsPanel.Visibility = Visibility.Hidden;
            }
        }
    }
}
